package com.kgcx.opc.common.utils.io;

import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.ftp.FTPSClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Properties;

/**
 * @author 何凯
 * @version 0.1
 * @description
 * @time 2018/1/11 17:30
 * @since 0.1
 */
public class FtpsUtils {

    private static Logger logger = LoggerFactory.getLogger(FtpsUtils.class);
    private static FtpsUtils ftpsUtils;
    private FTPSClient ftpsClient;

    private String serverUrl; //服务器地址
    private String port; // 服务器端口
    private String username; // 用户登录名
    private String password; // 用户登录密码
    private String url;//远程图片地址
    private InputStream is; // 文件下载输入流

    /**
     * 私有构造方法
     */
    private FtpsUtils() {
        initConfig();
        if (null == ftpsClient) {
            ftpsClient = new FTPSClient();
        }
    }
    /**
     * 获取ftpsUtils对象实例
     *
     * @return ftpsUtils对象实例
     */
    public synchronized static FtpsUtils getInstance() {
        if (null == ftpsUtils) {
            ftpsUtils = new FtpsUtils();
        }
        return ftpsUtils;
    }

    /**
     * 初始化FTP服务器连接属性
     */
    public void initConfig() {
        // 构造Properties对象
        Properties properties = PropertiesUtil.getProperties("ftpConfig.properties");
        // 172.30.50.104ftp读取配置文件
        serverUrl = (String) properties.get("host"); // 设置服务器地址
        port = (String) properties.get("port"); // 设置端口
        username = (String) properties.get("userName"); // 设置用户名
        password = (String) properties.get("password"); // 设置密码
        url =(String) properties.get("url"); // 设置密码
    }

    /**
     * 连接（配置通用连接属性）至服务器
     *
     * @param remotePath
     *            服务器名称
     * @param remotePath
     *            当前访问目录
     * @return <b>true</b>：连接成功 <br/>
     *         <b>false</b>：连接失败
     */
    public boolean connectToTheServer(String remotePath) {
        // 定义返回值
        boolean result = false;
        try {
            // 连接至服务器，端口默认为21时，可直接通过URL连接
            ftpsClient.connect(serverUrl, Integer.parseInt(port));
            // 登录服务器
            ftpsClient.login(username, password);
            // 判断返回码是否合法
            if (!FTPReply.isPositiveCompletion(ftpsClient.getReplyCode())) {
                // 不合法时断开连接
                ftpsClient.disconnect();
                // 结束程序
                return result;
            }
            //设置文件传输模式
            //被动模式
//          ftpsClient.enterLocalPassiveMode();
            //创建目录
            ftpsClient.makeDirectory(remotePath);
            // 设置文件操作目录
            result = ftpsClient.changeWorkingDirectory(remotePath);
            // 设置文件类型，二进制
            result = ftpsClient.setFileType(ftpsClient.BINARY_FILE_TYPE);
            // 设置缓冲区大小
            ftpsClient.setBufferSize(3072);
            // 设置字符编码
            ftpsClient.setControlEncoding("UTF-8");

        } catch (IOException e) {
            logger.error("连接FTP服务器异常",e);
            throw new RuntimeException("连接FTP服务器异常" , e);
        }
        return result;
    }

    /**
     * 上传文件至FTP服务器
     *
     * @param storePath
     *            服务器名称
     * @param storePath
     *            上传文件存储路径
     * @param fileName
     *            上传文件存储名称
     * @param is
     *            上传文件输入流
     * @return <b>true</b>：上传成功 <br/>
     *         <b>false</b>：上传失败
     */
    public boolean storeFile( String storePath, String fileName, InputStream is) {
        boolean result = false;
        try {
            // 连接至服务器
            result = connectToTheServer(storePath);
            // 判断服务器是否连接成功
            if (result) {
                // 上传文件
                result = ftpsClient.storeFile(fileName, is);
            }
            // 关闭输入流
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 判断输入流是否存在
            if (null != is) {
                try {
                    // 关闭输入流
                    is.close();
                } catch (IOException e) {
                    logger.error("上传文件至FTP异常"+e.getMessage());
                    throw new RuntimeException("上传文件至FTP异常" , e);
                }
            }
            // 登出服务器并断开连接
            ftpsUtils.logout();
        }
        return result;
    }

    /**
     * 下载FTP服务器文件至本地<br/>
     * 操作完成后需调用logout方法与服务器断开连接
     *
     * @param remotePath
     *            服务器名称
     * @param remotePath
     *            下载文件存储路径
     * @param fileName
     *            下载文件存储名称
     * @return <b>InputStream</b>：文件输入流
     */
    public InputStream retrieveFile(String remotePath,String fileName) {
        try {
            boolean result = false;
            // 连接至服务器
            result = connectToTheServer(remotePath);
            // 判断服务器是否连接成功
            if (result) {
                // 获取文件输入流
                is = ftpsClient.retrieveFileStream(fileName);
            }
        } catch (IOException e) {
            logger.error("从FTP下载文件到本地异常"+e.getMessage());
            throw new RuntimeException("从FTP下载文件到本地异常" , e);
        }
        return is;
    }

    /**
     * Description: 从FTP服务器下载文件
     *
     * @Version1.0 Jul 27, 2008 5:32:36 PM by 崔红保（cuihongbao@d-heaven.com）创建
     * @param remotePath
     *            FTP服务器上的相对路径
     * @param fileName
     *            要下载的文件名
     * @param localPath
     *            下载后保存到本地的路径
     * @return
     */
    public boolean retrieveFile(String remotePath, String fileName,String localPath) {
        // 初始表示下载失败
        boolean success = false;
        //表示是否连接成功
        boolean result = false;
        File file = new File(localPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        try {
            // 连接至服务器
            result = connectToTheServer(remotePath);
            if(result){
                // 列出该目录下所有文件
                FTPFile[] fs = ftpsClient.listFiles();
                // 遍历所有文件，找到指定的文件
                for (FTPFile ff : fs) {
                    if (ff.getName().equals(fileName)) {
                        // 根据绝对路径初始化文件
                        File localFile = new File(localPath + "/" + ff.getName());
                        //输出流
                        OutputStream is = new FileOutputStream(localFile);
                        //下载文件
                        success=ftpsClient.retrieveFile(ff.getName(), is);
                        is.close();
                    }
                }
            }

        } catch (IOException e) {
            logger.error("从FTP服务器下载文件异常",e);
        } finally {
            // 登出服务器并断开连接
            ftpsUtils.logout();
        }
        return success;
    }


    /**
     * 删除FTP服务器文件
     *
     * @param remotePath
     *            服务器名称
     * @param remotePath
     *            当前访问目录
     * @param fileName
     *            文件存储名称
     * @return <b>true</b>：删除成功 <br/>
     *         <b>false</b>：删除失败
     */
    public boolean deleteFile(String remotePath,String fileName) {
        boolean result = false;
        // 连接至服务器
        result = connectToTheServer(remotePath);
        // 判断服务器是否连接成功
        if (result) {
            try {
                // 删除文件
                result = ftpsClient.deleteFile(fileName);
            } catch (IOException e) {
                logger.error("删除FTP服务器上的 文件异常"+e.getMessage());
                throw new RuntimeException("删除FTP服务器上的 文件异常" , e);
            } finally {
                // 登出服务器并断开连接
                ftpsUtils.logout();
            }
        }
        return result;
    }

    /**
     * 检测FTP服务器文件是否存在
     *
     * @param remotePath
     *            服务器名称
     * @param remotePath
     *            检测文件存储路径
     * @param fileName
     *            检测文件存储名称
     * @return <b>true</b>：文件存在 <br/>
     *         <b>false</b>：文件不存在
     */
    public boolean checkFile( String remotePath,String fileName) {
        boolean result = false;
        try {
            // 连接至服务器
            result = connectToTheServer(remotePath);
            // 判断服务器是否连接成功
            if (result) {
                // 默认文件不存在
                result = false;
                // 获取文件操作目录下所有文件名称
                String[] remoteNames = ftpsClient.listNames();
                // 循环比对文件名称，判断是否含有当前要下载的文件名
                for (String remoteName : remoteNames) {
                    if (fileName.equals(remoteName)) {
                        result = true;
                    }
                }
            }
        } catch (IOException e) {
            logger.error("检查FTP文件是否存在异常"+e.getMessage());
            throw new RuntimeException("检查FTP文件是否存在异常" , e);
        } finally {
            // 登出服务器并断开连接
            ftpsUtils.logout();
        }
        return result;
    }

    /**
     * 登出服务器并断开连接
     *            ftpsClient对象实例
     * @return <b>true</b>：操作成功 <br/>
     *         <b>false</b>：操作失败
     */
    public boolean logout() {
        boolean result = false;
        if (null != is) {
            try {
                // 关闭输入流
                is.close();
            } catch (IOException e) {
                logger.error("登录FTP服务器异常"+e.getMessage());
                throw new RuntimeException("登录FTP服务器异常" , e);
            }
        }
        if (null != ftpsClient) {
            try {
                // 登出服务器
                result = ftpsClient.logout();
            } catch (IOException e) {
                logger.error("登录FTP服务器异常"+e.getMessage());
                throw new RuntimeException("登录FTP服务器异常" , e);
            } finally {
                // 判断连接是否存在
                if (ftpsClient.isConnected()) {
                    try {
                        // 断开连接
                        ftpsClient.disconnect();
                    } catch (IOException e) {
                        logger.error("关闭FTP服务器异常"+e.getMessage());
                        throw new RuntimeException("关闭FTP服务器异常" , e);
                    }
                }
            }
        }
        return result;
    }





    /**
     * Description: 从FTP服务器下载文件
     *
     * @param url
     *            FTP服务器hostname
     * @param port
     *            FTP服务器端口
     * @param username
     *            FTP登录账号
     * @param password
     *            FTP登录密码
     * @param remotePath
     *            FTP服务器上的相对路径
     * @param fileName
     *            要下载的文件名
     * @param localPath
     *            下载后保存到本地的路径
     * @return
     */
    public static boolean downFile(String url, int port, String username,
            String password, String remotePath, String fileName,
            String localPath) {
        // 初始表示下载失败
        boolean success = false;
        // 创建ftpsClient对象
        FTPSClient ftp = new FTPSClient();
        try {
            int reply;
            // 连接FTP服务器
            // 如果采用默认端口，可以使用ftp.connect(url)的方式直接连接FTP服务器
            ftp.connect(url, port);
            reply = ftp.getReplyCode();
            /*
             * 判断是否连接成功
             */
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return success;
            } else {
                // 登录ftp
                if (ftp.login(username, password)) {
                    // 转到指定下载目录
                    ftp.changeWorkingDirectory(remotePath);
                    // 列出该目录下所有文件
                    FTPFile[] fs = ftp.listFiles();
                    // 遍历所有文件，找到指定的文件
                    for (FTPFile ff : fs) {
                        if (ff.getName().equals(fileName)) {
                            // 根据绝对路径初始化文件
                            File localFile = new File(localPath + "/"
                                    + ff.getName());
                            // 输出流
                            OutputStream is = new FileOutputStream(localFile);
                            // 下载文件
                            ftp.retrieveFile(ff.getName(), is);
                            is.close();
                        }
                    }
                    // 退出ftp
                    ftp.logout();
                    // 下载成功
                    success = true;
                }
            }
        } catch (IOException e) {
            logger.error("从FTP服务器下载文件异常"+e.getMessage());
            throw new RuntimeException("从FTP服务器下载文件异常" , e);
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.error("关闭FTP连接异常"+ioe.getMessage());
                    throw new RuntimeException("关闭FTP连接异常" , ioe);
                }
            }
        }
        return success;
    }

    /**
     * 读取本地TXT
     *
     * @param filepath
     *            txt文件目录即文件名
     */

    public ArrayList<String> readtxt(String filepath) {
        ArrayList<String> readList = new ArrayList<String>();
        ArrayList retList = new ArrayList();
        try {
            String temp = null;
            File f = new File(filepath);
            String adn = "";
            // 指定读取编码用于读取中文
            InputStreamReader read = new InputStreamReader(new FileInputStream(
                    f), "UTF-8");
            BufferedReader reader = new BufferedReader(read);
            // bufReader = new BufferedReader(new FileReader(filepath));
            do {
                temp = reader.readLine();
                readList.add(temp);
            } while (temp != null);
            read.close();
        } catch (Exception e) {
            // TODO: handle exception
            logger.error("读取本地txt异常"+e.getMessage());
            throw new RuntimeException("读取本地txt异常" , e);
        }
        return readList;
    }

    /**
     * 把配置文件先写到本地的一个文件中取
     *
     * @param ftpPath
     * @param str
     * @return
     */
    public boolean write(String fileName, String fileContext,
            String writeTempFielPath) {
        try {
            logger.info("开始写配置文件");
            File f = new File(writeTempFielPath + "/" + fileName);
            if(!f.exists()){
                if(!f.createNewFile()){
                    logger.info("文件不存在，创建失败!");
                }
            }
            BufferedWriter bw = new BufferedWriter(new FileWriter(f, true));
            bw.write(fileContext.replaceAll("\n", "\r\n"));
            bw.flush();
            bw.close();
            return true;
        } catch (Exception e) {
            logger.error("写文件没有成功");
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 从远程获取图片传入ftp服务目录
     * @param name
     * @return
     */
    public Boolean uploadFileByRemote(String name){
        boolean flag = false;
        try {
        //new一个URL对象
        URL urls = new URL(url+"/"+name);
        //打开链接
        HttpURLConnection conn = (HttpURLConnection)urls.openConnection();
        //设置请求方式为"GET"
        conn.setRequestMethod("GET");
        //超时响应时间为5秒
        conn.setConnectTimeout(50 * 1000);
        //通过输入流获取图片数据
        InputStream inStream = conn.getInputStream();
        FtpsUtils ftp = FtpsUtils.getInstance();
        String remotePath = "/swapfiles";
        StringBuffer fileName = new StringBuffer(name);
        if(!name.endsWith(".jpg")){
            fileName.append(".jpg");
        }
        flag = ftp.storeFile(remotePath, fileName.toString(),inStream);
        logger.info("文件上传结果："+flag);

      } catch (Exception e) {
          flag = false;
          logger.debug(e.getMessage());
          e.printStackTrace();

      }
       return flag;
    }
    /**
     *
     * @Description： 测试连接ftP服务器
     * @author: hekai
     * @date:
     * @param args
     */
    public static void main(String[] args) throws  Exception{
        FtpsUtils ftp  = new FtpsUtils();
        ftp.uploadFileByRemote("15r58PIChmX_1024.jpg");
       /*try {
        //new一个URL对象
        URL urls = new URL(this.url+"/"+"15r58PIChmX_1024.jpg");
        //打开链接
        HttpURLConnection conn = (HttpURLConnection)urls.openConnection();
        //设置请求方式为"GET"
        conn.setRequestMethod("GET");
        //超时响应时间为5秒
        conn.setConnectTimeout(5 * 1000);
        //通过输入流获取图片数据
        InputStream inStream = conn.getInputStream();

        ftpsUtils ftp = ftpsUtils.getInstance();
        //String localPath="http://image.hangkechina.com/15r58PIChmX_1024.jpg";
        String remotePath = "/photo";
        String fileName = "15r58PIChmX_1024.jpg";
        boolean flag = ftp.storeFile(remotePath, fileName,inStream);
        logger.info("文件上传结果："+flag);
      } catch (Exception e) {
          e.printStackTrace();
      }*/

        //文件下载
        //      InputStream in=ftp.retrieveFile(remotePath, fileName);
        //      StringBuffer resultBuffer = new StringBuffer();
        //      BufferedReader br = new BufferedReader(new InputStreamReader(in));
        //      String data = null;
        //      try {
        //          while ((data = br.readLine()) != null) {
        //              resultBuffer.append(data + "\n");
        //          }
        //      } catch (IOException e) {
        //          logger.error("文件读取错误。");
        //          e.printStackTrace();
        //      }
        //     System.out.println(resultBuffer.toString());


        //在FTP服务器上生成一个文件，并将一个字符串写入到该文件中
//      try {
//          InputStream input = new ByteArrayInputStream("一切只能靠自己！".getBytes("utf-8"));
//          boolean flag = ftp.storeFile(remotePath,"test.txt",input);
//          System.out.println(flag);
//      } catch (UnsupportedEncodingException e) {
//          e.printStackTrace();
//      }


    }
}
